/*
 * @(#)InterfaceClient.java
 * 1.0, 2013-01-24
 */
package de.hdm.gruppenkalender.team04.gui;

import de.hdm.gruppenkalender.team04.GruppenkalenderVerwaltung;
import de.hdm.gruppenkalender.team04.data.Alarm;
import de.hdm.gruppenkalender.team04.data.Kalender;
import de.hdm.gruppenkalender.team04.data.Kategorie;
import de.hdm.gruppenkalender.team04.data.Person;
import de.hdm.gruppenkalender.team04.data.Termin;
import de.hdm.gruppenkalender.team04.report.BerichtGenerator;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.sql.Timestamp;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 * In dieser Klasse werden alle Client-Requests als Methoden umgesetzt.
 * <p>
 * In Anlehung an:
 * de.hdm.rathke.bankInterface.InterfaceClient.java
 *
 * @author Prof. Dr. Christian Rathke
 *
 * @author Mathias Bendel (mb167)
 * @author Björn Fichnter (bf023)
 * @author Stefan Hettich (sh176)
 * @author René Kugel (rk044)
 * @author Mark Leonberger (ml072)
 * @author Marta Przybylski (mp070)
 *
 * @version 1.0, 2013-01-24
 *
 */
public class InterfaceClient {

    /**
     * Die Klasse InterfaceClient wird nur einmal instantiiert.
     * Man spricht hierbei von einem sogenannten <b>Singleton</b>.
     * <p>
     * Diese Variable ist durch den Bezeichner <code>static</code> nur einmal für
     * sämtliche eventuellen Instanzen dieser Klasse vorhanden. Sie speichert die
     * einzige Instanz dieser Klasse.
     *
     * @see #interfaceClient() 
     */
    private static InterfaceClient ic;
    private GruppenkalenderVerwaltung verwaltung = null;
    private BerichtGenerator berichtGenerator = null;
    private static String ip;
    // Standard-IP, die gesetzt wird, wenn keine Eingabe erfolgt.
    private final static String LOCALHOST_IP = "127.0.0.1";
    // Standard-Port, der gesetzt wird, wenn keine Eingabe erfolgt.
    private final static String PORT = "1099";

    /**
     * Geschützter Konstruktor - verhindert die Möglichkeit, mit new neue
     * Instanzen dieser Klasse zu erzeugen.
     */
    protected InterfaceClient() {
    }

    /**
     * Diese statische Methode kann aufgrufen werden durch
     * <code>InterfaceClient.interfaceClient()</code>. Sie stellt die
     * Singleton-Eigenschaft sicher, indem Sie dafür sorgt, daß nur eine einzige
     * Instanz von <code>InterfaceClient</code> existiert.
     *
     * @return {@link InterfaceClient}-Objekt.
     * @see #ic
     */
    public static InterfaceClient interfaceClient() {
        if (ic == null) {

            ic = new InterfaceClient();

            ip = JOptionPane.showInputDialog(null,
                    "Geben Sie die Server-IP an: (leer lassen für localhost!)",
                    "Anmeldung am System", JOptionPane.QUESTION_MESSAGE);
            if (ip == null) {
                // Nutzer hat Dialog abgebrochen.
                System.exit(0);
            } else if (ip.equals("")) {
                // Nutzer hat keine Eingabe getätigt, deshalb localhost.
                ip = LOCALHOST_IP + ":" + PORT;
                System.out.println("Suche Server mit IP: " + ip);
            } else if (ip.indexOf(":") == -1) {
                ip += (":" + PORT);
                System.out.println("Suche Server mit IP: " + ip);
            }
        }

        return ic;
    }

    /**
     * Stellt Verbindung zum RMI-Server her.
     */
    private void stelleServerVerbindungHer() {
        try {

            verwaltung = (GruppenkalenderVerwaltung) Naming.lookup(
                    "rmi://" + ip + "/GruppenkalenderVerwaltung");
            berichtGenerator = verwaltung.getBerichtGenerator();
            System.out.println("Server-Verbindung hergestellt...");

        } catch (NotBoundException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);

        } catch (MalformedURLException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);

        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);

        }
    }

    /**
     * Erstellt eine neue Person
     *
     * @param   vorname
     * @param   nachname
     * @param   raum
     * @param   telefon
     * @param   email
     * @return  Person      die erstellte Person.
     */
    public Person erstellePerson(String vorname, String nachname, String raum,
            String telefon, String email) {
        Person person = null;

        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        try {
            person = verwaltung.erstellePerson(vorname, nachname, raum, telefon,
                    email);

        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }
        return person;
    }

    /**
     * Erstellt neuen Termin oder neue Termine (inkl. Wiederholungen und
     * Alarmen)
     * 
     * @param   start
     * @param   ende
     * @param   titel
     * @param   ort
     * @param   beschreibung
     * @param   kategorieId
     * @param   erstellerId
     * @param   kalenderId
     * @param   teilnehmerId
     * @param   alarmStart
     * @param   anzahlWiederholungen
     * @param   abstandWiederholungen
     */
    public void erstelleTermine(Timestamp start, Timestamp ende, String titel,
            String ort, String beschreibung, int kategorieId, int erstellerId,
            int kalenderId, Vector<Integer> teilnehmerId, Timestamp alarmStart,
            int anzahlWiederholungen, int abstandWiederholungen) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }
        try {
            verwaltung.erstelleTermine(start, ende, titel, ort, beschreibung,
                    kategorieId, erstellerId, kalenderId, teilnehmerId,
                    alarmStart, anzahlWiederholungen, abstandWiederholungen);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).
                    log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Erstellt einen neuen Alarm
     *
     * @param   start
     * @param   titel
     * @param   kategorieId
     * @param   erstellerId
     * @param   kalenderId
     * @param   gueltigFuerId
     * @return  Alarm           der erstellte Alarm.
     */
    public Alarm erstelleAlarm(Timestamp start, String titel, int kategorieId,
            int erstellerId, int kalenderId, int gueltigFuerId) {
        Alarm alarm = null;

        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }
        try {
            alarm = verwaltung.erstelleAlarm(start, titel, kategorieId,
                    erstellerId, kalenderId, gueltigFuerId);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).
                    log(Level.SEVERE, null, ex);
        }

        return alarm;
    }

    /**
     * Erstellt eine neue Kategorie
     *
     * @param   name
     * @return  Kategorie   erstellte Kategorie
     */
    public Kategorie erstelleKategorie(String name) {
        Kategorie kategorie = null;

        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        try {
            kategorie = verwaltung.erstelleKategorie(name);

        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }
        return kategorie;
    }

    /**
     * Erstellt neuen Kalender.
     * 
     * @param   bezeichnung
     * @param   besitzerId
     * @param   berechtigteIds
     * @return  Kalender        erstellter Kalender.
     */
    public Kalender erstelleKalender(String bezeichnung, int besitzerId,
            Vector<Integer> berechtigteIds) {
        Kalender kalender = null;

        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }
        try {
            kalender = verwaltung.erstelleKalender(bezeichnung, besitzerId,
                    berechtigteIds);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).
                    log(Level.SEVERE, null, ex);
        }

        return kalender;
    }

    /**
     * Bearbeitet eine Person und übergibt dazu die nachfolgenden Parameter
     *
     * @param   person
     * @param   vorname
     * @param   nachname
     * @param   raum
     * @param   telefon
     * @param   email
     * @return  Person      bearbeitete Person
     */
    public Person bearbeitePerson(Person person, String vorname, String nachname,
            String raum, String telefon, String email) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        try {
            person.setVorname(vorname);
            person.setNachname(nachname);
            person.setRaum(raum);
            person.setTelefon(telefon);
            person.setEmail(email);

            verwaltung.speichern(person);

        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }

        return person;
    }

    /**
     * Bearbeitet eine übergebene Kategorie
     *
     * @param   kategorie
     * @param   name
     * @return  Kategorie   die bearbeitete Kategorie
     */
    public Kategorie bearbeiteKategorie(Kategorie kategorie, String name) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        try {
            kategorie.setName(name);

            verwaltung.speichern(kategorie);

        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }

        return kategorie;
    }

    /**
     * Bearbeitet einen Kalender und übergibt dazu die nachfolgenden Parameter
     *
     * @param   kalender
     * @param   bezeichnung
     * @param   besitzerId
     * @param   berechtigeIds
     * @return  Kalender        der bearbeitete Kalender
     */
    public Kalender bearbeiteKalender(Kalender kalender, String bezeichnung,
            int besitzerId, Vector<Integer> berechtigeIds) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }
        try {
            kalender.setBezeichnung(bezeichnung);
            kalender.setBesitzerId(besitzerId);
            kalender.setZugriffsberechtigteId(berechtigeIds);

            verwaltung.speichern(kalender);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).
                    log(Level.SEVERE, null, ex);
        }
        return kalender;
    }

    /**
     * Bearbeitet einen Alarm und übergibt dazu die nachfolgenden Parameter
     *
     * @param   alarm
     * @param   start
     * @param   titel
     * @param   kategorieId
     * @param   erstellerId
     * @param   kalenderId
     * @param   gueltigFuerId
     * @return  Alarm           der bearbeitete Alarm
     */
    public Alarm bearbeiteAlarm(Alarm alarm, Timestamp start, String titel,
            int kategorieId, int erstellerId, int kalenderId, int gueltigFuerId) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        try {
            alarm.setStart(start);
            alarm.setEnde(null);
            alarm.setTitel(titel);
            alarm.setOrt("");
            alarm.setBeschreibung("");
            alarm.setKategorieId(kategorieId);
            alarm.setErstellerId(erstellerId);
            alarm.setKalenderId(kalenderId);
            alarm.setFolgeterminId(0);
            alarm.setGueltigFuerId(gueltigFuerId);

            verwaltung.speichern(alarm);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).
                    log(Level.SEVERE, null, ex);
        }

        return alarm;
    }

    /**
     * Löscht eine übergebene Person.
     * 
     * @param person
     */
    public void loeschePerson(Person person) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        try {
            verwaltung.loeschePerson(person);

        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }
    }

    /**
     * Löscht einen übergebenen Termin.
     * 
     * Je nach übergebenen Parametern werden alle Folgetermine ebenfalls
     * gelöscht.
     *
     * @param termin
     * @param nutzer
     * @param allesLoeschen
     */
    public void loescheTermin(Termin termin, Person nutzer,
            boolean allesLoeschen) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        try {
            verwaltung.loescheTermin(termin, nutzer, allesLoeschen);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }
    }

    /**
     * löscht den übergebenen Alarm
     *
     * @param alarm
     */
    public void loescheAlarm(Alarm alarm) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        try {
            verwaltung.loescheAlarm(alarm);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }
    }

    /**
     * Löscht eine übergebene Kategorie.
     *
     * @param kategorie
     */
    public void loescheKategorie(Kategorie kategorie) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        try {
            verwaltung.loescheKategorie(kategorie);

        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }
    }

    /**
     * Löscht einen übergebenen Kalender.
     * 
     * @param kalender
     */
    public void loescheKalender(Kalender kalender) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        try {
            verwaltung.loescheKalender(kalender);

        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }
    }

    /**
     * Ermittelt alle Personen.
     *
     * @return Vector<Person> mit allen Personen.
     */
    public Vector<Person> ermittleAllePersonen() {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        Vector<Person> personen = new Vector<Person>();

        try {
            personen = verwaltung.ermittleAllePersonen();
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }

        return personen;
    }

    /**
     * Ermittelt alle Alarme.
     *
     * @return Vector<Alarm> mit allen Alarmen
     */
    public Vector<Alarm> ermittleAlleAlarme() {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        Vector<Alarm> alarme = new Vector<Alarm>();

        try {
            alarme = verwaltung.ermittleAlleAlarme();
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }

        return alarme;
    }

    /**
     * Ermittelt alle Alarme einer übergebenen Person.
     *
     * @param   person
     * @return  Vector<Alarm> mit allen Termin von übergebener Person
     */
    public Vector<Alarm> ermittleAlleAlarmeVon(Person person) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        Vector<Alarm> alarme = new Vector<Alarm>();

        try {
            alarme = verwaltung.ermittleAlleAlarmeVonPerson(person);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }

        return alarme;
    }

    /**
     * Ermittelt alle Termine
     *
     * @return Vector<Termin> mit allen Terminen.
     */
    public Vector<Termin> ermittleAlleTermine() {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        Vector<Termin> termine = new Vector<Termin>();

        try {
            termine = verwaltung.ermittleAlleTermine();

        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }

        return termine;
    }

    /**
     * Ermittelt alle Termine von übergebener Person.
     *
     * @param   person
     * @return  Vector<Termin> mit allen Terminen von übergebener Person.
     */
    public Vector<Termin> ermittleAlleTermineVon(Person person) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        Vector<Termin> termine = new Vector<Termin>();

        try {
            termine = verwaltung.ermittleAlleTermineVonPerson(person);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }

        return termine;
    }

    /**
     * Ermittelt alle Kalender.
     *
     * @return Vector<Kalender> mit allen Kalendern.
     */
    public Vector<Kalender> ermittleAlleKalender() {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        Vector<Kalender> kalender = new Vector<Kalender>();
        try {
            kalender = verwaltung.ermitlleAlleKalender();
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).
                    log(Level.SEVERE, null, ex);
        }

        return kalender;
    }

    /**
     * Ermittelt alle Kalender von übergebener Person.
     *
     * @param   person
     * @return  Vector<Kalender> mit allen Kalendern von übergebener Person.
     */
    public Vector<Kalender> ermittleAlleKalenderVon(Person person) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        Vector<Kalender> kalenders = new Vector<Kalender>();

        try {
            kalenders = verwaltung.ermittleAlleKalenderVonPerson(person);

        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }

        return kalenders;
    }

    /**
     * Ermittelt alle Kategorien.
     *
     * @return Vector<Kategorie> mit allen Kategorien.
     */
    public Vector<Kategorie> ermittleAlleKategorien() {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        Vector<Kategorie> kategorien = new Vector<Kategorie>();

        try {
            kategorien = verwaltung.ermittleAlleKategorien();
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).log(Level.SEVERE,
                    null, ex);
        }

        return kategorien;
    }

    /**
     * Ermittelt Alarm mit bestimmtem Schlüssel.
     *
     * @param   id
     * @return  Alarm
     */
    public Alarm ermittleAlarmViaSchluessel(int id) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }
        try {
            return verwaltung.ermittleAlarmViaSchluessel(id);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).
                    log(Level.SEVERE, null, ex);
        }
        return null;
    }

    /**
     * Ermittelt Person mit übergebenem Schlüssel.
     *
     * @param   id
     * @return  Person
     */
    public Person ermittlePersonViaSchluessel(int id) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }
        try {
            return verwaltung.ermittlePersonViaSchluessel(id);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).
                    log(Level.SEVERE, null, ex);
        }

        return null;
    }

    /**
     * Ermittelt Termin-Id anhand übergebener Folgetermin-Id.
     *
     * @param   id
     * @return  int Termin-Id.
     */
    public int ermittleTerminIdViaFolgetermin(int id) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }
        try {
            return verwaltung.ermittleTerminIdViaFolgetermin(id);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).
                    log(Level.SEVERE, null, ex);
        }

        return 0;
    }

    /**
     * Ermittelt Termin anhand übergebener Termin-Id.
     *
     * @param   id
     * @return  Termin
     */
    public Termin ermittleTerminViaSchluessel(int id) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }
        try {
            return verwaltung.ermittleTerminViaSchluessel(id);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).
                    log(Level.SEVERE, null, ex);
        }

        return null;
    }

    /**
     * Prüft, ob die angegebene Termin-Id eine Wiederholung ist.
     * 
     * @param   terminId
     * @return  true oder false
     */
    public boolean istWiederholung(int terminId) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        try {
            return verwaltung.istWiederholung(terminId);

        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).
                    log(Level.SEVERE, null, ex);
        }
        return false;
    }

    /**
     * Ermittelt den Status der Wiederholungen des Termins.
     *
     * @param   termin
     * @return  int-Array mit Abstand und Anzahl
     */
    public int[] ermittleStatusWiederholungen(Termin termin) {
        if (verwaltung == null) {
            this.stelleServerVerbindungHer();
        }

        int[] result = new int[2];

        try {
            result[0] = verwaltung.ermittleAbstandWiederholung(termin);
            result[1] = verwaltung.ermittleAnzahlWiederholung(termin);
        } catch (RemoteException ex) {
            Logger.getLogger(InterfaceClient.class.getName()).
                    log(Level.SEVERE, null, ex);
        }

        return result;
    }
}
